﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace MvcShop
{
    /*
    public static class RouteExpression
    {
        private static ActionRouteDescriptorCache s_actionRouteDescriptorCache = new ActionRouteDescriptorCache();

        public static MethodCallExpression GetActionCall<TController>(Expression<Action<TController>> action) where TController : Controller
        {
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            MethodCallExpression call = action.Body as MethodCallExpression;
            if (call == null)
            {
                throw new ArgumentException("The action must be a method call.", "action");
            }

            return call;
        }

        public static VirtualPathBuilder Parse<TController>(Expression<Action<TController>> action, RequestContext requestContext) where TController : Controller
        {
            var call = GetActionCall(action);

            var actionDescriptor = s_actionRouteDescriptorCache.Get(call.Method);
            var rvd = new RouteValueDictionary();

            rvd.Add("controller", actionDescriptor.ControllerName);
            rvd.Add("action", actionDescriptor.Name);
            rvd.Add("area", actionDescriptor.Area);

            AddParameterValues(requestContext, rvd, call, actionDescriptor);

            return new VirtualPathBuilder(actionDescriptor.RouteName, rvd);
        }

        private static void AddParameterValues(RequestContext requestContext, RouteValueDictionary rvd, MethodCallExpression call, ActionRouteDescriptor actionDescriptor)
        {
            ParameterInfo[] parameters = call.Method.GetParameters();

            for (int i = 0; i < parameters.Length; i++)
            {
                var parameterInfo = parameters[i];
                var argumentExpr = call.Arguments[i];

                if (!ParameterShouldBeIgnored(argumentExpr))
                {
                    var parameterValue = Eval(argumentExpr);

                    var routeBinder = actionDescriptor.GetRouteBinder(parameterInfo);

                    if (routeBinder == null)
                    {
                        rvd.Add(parameterInfo.Name, parameterValue);
                    }
                    else
                    {
                        var bindingContext = new RouteBindingContext
                        {
                            Model = parameterValue,
                            ModelName = parameterInfo.Name,
                            ModelType = parameterInfo.ParameterType
                        };

                        var values = routeBinder.BindRoute(requestContext, bindingContext);

                        if (values != null && values.Count > 0)
                        {
                            foreach (var pair in values)
                            {
                                rvd.Add(pair.Key, pair.Value);
                            }
                        }
                    }
                }
            }
        }

        private static bool ParameterShouldBeIgnored(Expression arg)
        {
            var call = arg as MethodCallExpression;
            if (call == null) return false;

            if (call.Method.DeclaringType != typeof(It)) return false;
            if (call.Method.Name != "IsAny") return false;

            return true;
        }

        private static FastEvaluator s_parameterEvaluator = new FastEvaluator();

        private static object Eval(Expression exp)
        {
            ConstantExpression ce = exp as ConstantExpression;
            if (ce != null) return ce.Value;

            return s_parameterEvaluator.Eval(exp);
        }
    }
     * */

}
